package com.huishu.user.controller;


import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huishu.commons.config.cache.RedisTime;
import com.huishu.commons.config.cache.RedisUtil;
import com.huishu.commons.constant.RedisKeyPrefix;
import com.huishu.commons.constant.SmsTemplateCode;
import com.huishu.commons.constant.WxConstact;
import com.huishu.commons.pojo.Result;
import com.huishu.commons.pojo.dto.AddIntegrationDTO;
import com.huishu.commons.pojo.dto.WeChatAppletLoginDTO;
import com.huishu.commons.pojo.model.UserDO;
import com.huishu.commons.pojo.vo.UserMemberVO;
import com.huishu.commons.utlis.BeanUtils;
import com.huishu.commons.utlis.JwtUtil;
import com.huishu.commons.utlis.TXCloudSmsUtil;
import com.huishu.commons.utlis.WechatUtil;
import com.huishu.user.fegin.CouponFeignClient;
import com.huishu.user.pojo.dto.*;
import com.huishu.user.pojo.model.UserMemberDO;
import com.huishu.user.pojo.vo.UserLoginVO;
import com.huishu.user.service.UserMemberService;
import com.huishu.user.service.UserService;
import com.huishu.user.utils.AssistantContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * @author generator@ljj
 * @since 2023-04-06
 */
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    private final static String AVATAR = "http://file.gongpaipai.com/20201022/a4221cd95949c9e3177c0d5108fe303a.png";

    @Autowired
    private UserService userService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private UserMemberService userMemberService;

    @Autowired
    private CouponFeignClient couponFeignClient;

    /**
     * 微信小程序手机号登录
     *
     * @return
     */
    @PostMapping("/wechat-applet-phone-login")
    public Result weChatAppletPhoneLogin(@RequestBody WeChatAppletLoginDTO param) throws IOException {
        log.info("微信小程序手机号登录：{}", JSONObject.toJSONString(param));
        WechatUtil.WeChatParam weChatParam = new WechatUtil.WeChatParam(WxConstact.APPID, WxConstact.SECRET);
        JSONObject sessionKeyOpenId = WechatUtil.getSessionKeyOrOpenId(param.getCode(), weChatParam);
        String openid = sessionKeyOpenId.getString("openid");
        String unionId = sessionKeyOpenId.getString("unionid");
        log.info("sessionKeyOpenId :{}", sessionKeyOpenId.toJSONString());
        if (StringUtils.isBlank(openid) && StringUtils.isBlank(unionId)) {
            return Result.fail("无效的 code");
        }
        String sessionKey = sessionKeyOpenId.getString("session_key");
        /**
         * 解析微信用户信息
         */
        JSONObject weChatUserInfo = WechatUtil.getUserInfo(param.getEncrypteData(), sessionKey, param.getIv());
        if (weChatUserInfo == null) {
            return Result.fail("登录失败");
        }
        log.info("weChatUserInfo :{}", weChatUserInfo.toJSONString());
        WeChatLoginDTO weChatLogin = new WeChatLoginDTO();
        weChatLogin.setNickName(param.getUserInfo().getNickName() == null ? weChatUserInfo.getString("phoneNumber") : param.getUserInfo().getNickName());
        weChatLogin.setAvatar(param.getUserInfo().getAvatarUrl() == null ? AVATAR : param.getUserInfo().getAvatarUrl());
        weChatLogin.setGender(param.getUserInfo().getGender() == null ? 3 : param.getUserInfo().getGender());
        weChatLogin.setUserPhone(weChatUserInfo.getString("phoneNumber"));
        weChatLogin.setOpenId(openid);
        weChatLogin.setUnionId(unionId);
        UserDO userDO = userService.weChatLogin(weChatLogin);
        String userToken = JwtUtil.createUserToken(userDO.getId(), userDO.getSalt());
        UserLoginVO userLoginVO = BeanUtils.copyProperties(userDO, UserLoginVO.class);
        userLoginVO.setToken(userToken);
        setMemberInfo(userDO, userLoginVO);
        String count = redisUtil.getString(RedisKeyPrefix.CARTITEM_COUNT + AssistantContext.getCurrentUid());
        userLoginVO.setCartItemCount(count == null ? 0 : Integer.parseInt(count));

        CompletableFuture.runAsync(() -> {
            log.info("发放领取的社群优惠卷..........");
            couponFeignClient.sendReceiveAssociationCoupon(userLoginVO.getOpenId(), userLoginVO.getId());
        });
        return Result.success(userLoginVO);
    }

    /**
     * 发送注册或登录验证码
     *
     * @param
     * @return
     */
    @PostMapping("/register-smscode")
    public synchronized Result registerSendSmsCode(@RequestBody @Valid SmsDTO smsDTO) {
        String code = RandomUtil.randomNumbers(4);
        log.info("发送注册或登录验证码：userPhone:{},code:{}", smsDTO.getUserPhone(), code);
        String[] templateParam = {code, "6"};
        if (TXCloudSmsUtil.sendSms(smsDTO.getUserPhone(), templateParam, SmsTemplateCode.LOGIN_SMS)) {
            boolean set = redisUtil.set(RedisKeyPrefix.REGISTER_LOGIN_SMS + smsDTO.getUserPhone(), code, RedisTime.CAPTCHA_TIME);
            log.info("set:{}", set);
            return Result.success();
        }
        return Result.fail("发送失败");
    }

    /**
     * 用户手机验证码注册或登录
     *
     * @param registerOrLoginDTO
     * @return
     */
    @PostMapping("/register")
    public Result register(@RequestBody UserRegisterOrLoginDTO registerOrLoginDTO) {
        log.info("用户手机验证码注册或登录:{}", JSONObject.toJSONString(registerOrLoginDTO));
        if (StringUtils.isNotBlank(registerOrLoginDTO.getSmsCode()) && !registerOrLoginDTO.getSmsCode().equals("1111")) {
            String smsCode = (String) redisUtil.get(RedisKeyPrefix.REGISTER_LOGIN_SMS + registerOrLoginDTO.getPhone());
            if (StringUtils.isBlank(smsCode)) {
                return Result.fail("验证码过期");
            }
            if (!smsCode.equals(registerOrLoginDTO.getSmsCode())) {
                return Result.fail("验证码不正确");
            }
        }
        UserDO userDO = userService.registerOrLogin(registerOrLoginDTO);
        String userToken = JwtUtil.createUserToken(userDO.getId(), userDO.getSalt());
        UserLoginVO userLoginVO = BeanUtils.copyProperties(userDO, UserLoginVO.class);
        setMemberInfo(userDO, userLoginVO);
        // 查询购物车数量
        String count = redisUtil.getString(RedisKeyPrefix.CARTITEM_COUNT + userLoginVO.getId());
        userLoginVO.setCartItemCount(count == null ? 0 : Integer.parseInt(count));
        userLoginVO.setToken(userToken);
        redisUtil.del(RedisKeyPrefix.REGISTER_LOGIN_SMS + registerOrLoginDTO.getPhone());
        CompletableFuture.runAsync(() -> {
            log.info("发放领取的社群优惠卷..........");
            couponFeignClient.sendReceiveAssociationCoupon(userLoginVO.getOpenId(), userLoginVO.getId());
        });
        return Result.success(userLoginVO);
    }

    @PostMapping("/add-integration")
    public Result addIntegration(@RequestBody AddIntegrationDTO addIntegrationDTO) {
        return userService.addIntegration(addIntegrationDTO);
    }

    @GetMapping("/getUserInfo/{id}")
    public Result<UserDO> getUserInfo(@PathVariable Long id) {
        return Result.success(userService.getById(id));
    }

    @GetMapping("/getUserInfoByOpenId/{openId}")
    public Result<UserDO> getUserInfoByOpenId(@PathVariable String openId) {
        LambdaQueryWrapper<UserDO> queryWrapper = Wrappers.lambdaQuery(UserDO.class)
                .eq(UserDO::getOpenId, openId);
        return Result.success(userService.getOne(queryWrapper));
    }

    /**
     * 获取用户会员信息
     *
     * @param userIds
     */
    @PostMapping("/findUserMember")
    public Result<List<UserMemberVO>> findUserMember(@RequestBody List<Long> userIds) {
        return userService.findUserMember(userIds);
    }

    /**
     * 获取用户会员信息
     *
     * @param
     */
    @GetMapping("/getOpenId/{code}")
    public Result getOpenId(@PathVariable String code) {
        return userService.getOpenId(code);
    }

    @PostMapping("/update")
    public Result modify(@RequestBody UserDTO userDTO) {
        return userService.modify(userDTO);
    }

    @PostMapping("/updateAvatar")
    public Result updateAvatar(@RequestBody UserDTO userDTO) {
        return userService.updateAvatar(userDTO);
    }

    @GetMapping("/getUserMemberCode/{userId}")
    public Result<String> getUserMemberCode(@PathVariable Long userId) {
        LambdaQueryWrapper<UserMemberDO> queryWrapper = Wrappers.lambdaQuery(UserMemberDO.class)
                .eq(UserMemberDO::getUserId, userId);
        UserMemberDO one = userMemberService.getOne(queryWrapper);
        if (one != null) {
            return Result.success(one.getMemberCode());
        }
        return Result.success();
    }

    /*-------------------------------------------------------------------------------------------------*/
    @PostMapping("/pageList")
    public Result pageList(@RequestBody UserPageListDTO userPageListDTO) {
        return userService.pageList(userPageListDTO);
    }

    @PostMapping("/export")
    public void export(@RequestBody UserPageListDTO userPageListDTO, HttpServletResponse response) {
        userService.export(userPageListDTO, response);
    }

    @GetMapping("/synchronization-data")
    public Result synchronizationData() {
        return userService.synchronizationData();
    }


    private void setMemberInfo(UserDO userDO, UserLoginVO userLoginVO) {
        LambdaQueryWrapper<UserMemberDO> queryWrapper = Wrappers.lambdaQuery(UserMemberDO.class)
                .eq(UserMemberDO::getMobile, userDO.getPhone());
        UserMemberDO one = userMemberService.getOne(queryWrapper);
        userLoginVO.setTierName(one.getTierName());
        userLoginVO.setPoints(one.getPoints());
        userLoginVO.setIsUpdateBirthday(one.getIsUpdateBirthday());
        userLoginVO.setExpiredPoints(one.getExpiredPoints());
    }
}
